/*
 * @Description: 
 * @Version: 1.0
 * @Autor: ziwei
 * @Date: 2021-05-16 09:36:07
 * @LastEditors: ziwei
 * @LastEditTime: 2021-07-26 22:15:49
 */
import { compileToFunction } from "./compiler/index";
import { mountComponent } from "./observe/lifecycle";
import { initState } from "./state";
import { mergeOptions, nextTick } from "./utils";


export function initMixin(Vue) {
    //后续组件化开发的时候 vue.extend可以创造一个子组件，子组建可以继承Vue,子组建也可以调用_init方法
    Vue.prototype._init = function (options) {
        const vm = this;
        console.log("vm",vm);
        //把用户的选项放到vm上 这样其它方法都可以取道options vm.construstor有可能是子类(子组件)
        //因为全局定义的定容 会混合到当前实例上
        vm.$options = mergeOptions(vm.constructor.options,options);//为了后续扩展方法 都可以获取到optins选项
        debugger
        console.log("组件初始化会走vm.$options",vm.$options);
        initState(vm)

        if(vm.$options.el){
            //现在数据挂在到页面上

            //现在数据已经被劫持了数据变化需要更新视图 diff算法更i性能需要更新部分
            //vue -> template(写起来更符合直觉) -> jsx（更灵活）
            // vue3 template 写起来性能会更高一些 内部做了很多优化

            //template -> ast语法树（用来描述语法：css js html(用来描述语法本身的)的(虚拟dom用来描述节点的)->ast描述成一个树结构->将代码重组成js语法

            //模板编译原理（把template模板百年已成render函数->虚拟DOM -> diff算法比对虚拟dom ）template-exploere.vue.org
            
            //ast -> render返回 -> vnode -> 生成真实dom
            // 更新的时候再次调用render -> 新的vnode -> 新旧比对 -> 更新真实dom
            vm.$mount(vm.$options.el);
        }
    }
    Vue.prototype.$mount = function (el) {
        console.log("组件的初始化");
        const vm = this;
        const opts = vm.$options;
        el = document.querySelector(el);
        vm.$el = el;
        if (!opts.render) {
            let template = opts.template; // 取组件的template
            if (!template) {
                template = el.outerHTML;
            }
            let render = compileToFunction(template)
            opts.render = render;
        }
        mountComponent(vm)
    }
    Vue.prototype.$nextTick = nextTick
}
